package helper.base.math

import kotlin.math.exp
import kotlin.math.pow

object GetDecayingEpsilonHelper {
    // 根据当前的回合数（episode）和衰减率（decayRate）来计算epsilon
    // epsilon值会随着回合数的增加逐渐衰减
    fun t1GetEpsilon(
        episode: Int,
        decayRate: Double,
        minEpsilon: Double = 0.01,
    ): Double {
        return minEpsilon + (1.0 - minEpsilon) * exp(-decayRate * episode)
    }

    // 根据当前的回合比例（episodeFraction）和衰减因子（decayFactor）来计算epsilon
    fun t2GetEpsilon(
        episodeFraction: Double,
        decayFactor: Double = 0.99,
        minEpsilon: Double = 0.01,
    ): Double {
        return minEpsilon + (1.0 - minEpsilon) * decayFactor.pow(episodeFraction)
    }

    // 这是上面函数的一个重载版本，它会先计算回合比例然后调用上面的函数
    fun t2GetEpsilon(
        currentEpisode: Int,
        maxEpisodes: Int,
        decayFactor: Double = 0.99,
        minEpsilon: Double = 0.01,
    ): Double {
        return t2GetEpsilon(
            currentEpisode.toDouble() / maxEpisodes.toDouble(),
            decayFactor,
            minEpsilon,
        )
    }

    // 根据当前的回合比例（episodeFraction）和其他参数来计算epsilon
    fun t3GetEpsilon(
        episodeFraction: Double,
        gap: Double,
        a: Double = 10.0,
    ): Double {
        return (1 - episodeFraction) * (1 / (1 + exp(-a * gap)))
    }

    // 根据给定的epsilon值选择一个策略（aSNU或aUniformSNU）
    fun <E> selectStrategy(
        aSNU: E,
        epsilon: Double = 1.0,
        aUniformSNU: E = aSNU,
    ): E {
        return if (Math.random() < epsilon) {
            aUniformSNU
        } else {
            aSNU
        }
    }
}
